/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.gnarly.global;

import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import com.gnarly.model.Client;

/**
 * ClientManager.java
 * 
 * Manages clients
 * 
 * @author gnarly
 */
public class ClientManager {
	
	private static ClientManager singleton = null;
	
	public static ClientManager getSingleton() {
		if (singleton == null) {
			singleton = new ClientManager();
		}
		return singleton;
	}
	
	private static final int MAXIMUM_CLIENTS = 25;
	
	private Map<Integer, Client> clients;
	
	public ClientManager() {
		clients = new HashMap<Integer, Client>();
	}
	
	public void newClient(Socket socket) {
		int slot = -1, i = 1;
		do {
			if(clients.get(i) == null) {
				slot = i;
				break;
			}
			i++;
			if (i >= MAXIMUM_CLIENTS)
				i = 0;
		} while(i <= MAXIMUM_CLIENTS);
		Client client = new Client(socket);
		(new Thread(client)).start();
		if (slot == -1)
			return;
	}
	
	public void destruct() {
		for (Map.Entry<Integer, Client> entry : clients.entrySet()) {
			Client c = entry.getValue();
			if(c == null)
				continue;
			c.destruct();
		}
	}
	
	public int getClientCount() {
		return clients.size();
	}
	
	public void process() {
		for (Map.Entry<Integer, Client> entry : clients.entrySet()) {
			Client c = entry.getValue();
			if (c == null)
				continue;
			if (c.isDisconnected()) {
				removeClient(c);
			} else {
				c.tick();
			}
		}
		for (Map.Entry<Integer, Client> entry : clients.entrySet()) {
			Client c = entry.getValue();
			if (c == null)
				continue;
			if (c.isDisconnected()) {
				removeClient(c);
			} else {
				if (!c.isInitialized()) {
					c.initialize();
					c.setInitialized(true);
				}
			}
		}
	}
	
	private void removeClient(Client client) {
		client.destruct();
		System.gc();
	}
	
}
